package com.trs.publish.security;

import java.util.Collection;
import java.util.Iterator;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;


@Component
public class MyAccessDecisionManager implements AccessDecisionManager {

	  // decide 方法是判定是否拥有权限的决策方法，
	  //authentication 是释CustomUserService中循环添加到 GrantedAuthority 对象中的权限信息集合.
	  //object 包含客户端发起的请求的requset信息，可转换为 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
	  //configAttributes 为MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法返回的结果，此方法是为了判定用户请求的url 是否在权限表中，如果在权限表中，则返回给 decide 方法，用来判定用户是否有此权限。如果不在权限表中则放行。
	 @Override	
		public void decide(Authentication authentication, Object obj,
				Collection<ConfigAttribute> configAttributes)
				throws AccessDeniedException, InsufficientAuthenticationException {

		 if (null == configAttributes || configAttributes.size()<=0){  
	            return;  
	        }  
	        ConfigAttribute c;  
	        String needRole;  
	        Iterator<ConfigAttribute> ite = configAttributes.iterator();  
	        //遍历configAttributes看用户是否有访问资源的权限 
	        while (ite.hasNext()){  
	            c = ite.next();  
	            needRole = c.getAttribute(); 
	            //ga 为用户所被赋予的权限。 needRole 为访问相应的资源应该具有的权限。
	            for (GrantedAuthority ga : authentication.getAuthorities()){  
	                if (needRole.trim().equals(ga.getAuthority())){  
	                    return;  
	                }  
	            }  
	        }  
			/*
			 * 如果当前登录用户的角色名次与其请求资源所需角色的名称不匹配，抛出AccessDeniedException异常，
			 * 最终有spring security处理此异常，并根据安全配置文件的配置返回相关错误提示页面
			*/
	        throw new AccessDeniedException("no right");
	    }

	    @Override
	    public boolean supports(ConfigAttribute attribute) {
	        return true;
	    }

	    @Override
	    public boolean supports(Class<?> clazz) {
	        return true;
	    }
	    
	 
	}
